Skip to content

fix(tools): separate Tape runtime capabilities#1978

Merged
zerob13 merged 5 commits into
devfrom
fix/tape-capability-layering
Jul 15, 2026
Merged

fix(tools): separate Tape runtime capabilities#1978
zerob13 merged 5 commits into
devfrom
fix/tape-capability-layering

Conversation

@yyhhyyyyyy

@yyhhyyyyyy yyhhyyyyyy commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Separate Tape runtime capabilities from user-configurable Agent tools.
Tape is now treated as built-in runtime infrastructure rather than an optional tool group. Model-facing recall remains available when supported, while diagnostic and runtime-only capabilities stay outside the model tool catalog and Agent settings UI.
Closes #1975

Changes

  • Introduced a single Agent tool exposure policy:
    • tape_search: system-model
    • tape_context: system-model
    • tape_info: diagnostic
    • tape_anchors: diagnostic
    • tape_handoff: runtime-only
  • Split runtime and configurable Agent tool catalogs.
  • Removed Tape capabilities from Agent tool settings and disabled-tool toggles.
  • Exposed tape_search and tape_context as an atomic recall pair.
  • Kept all Tape names reserved to prevent same-name MCP tool collisions.
  • Rejected diagnostic and runtime-only Tape tools at the model dispatcher boundary.
  • Revalidated the DeepChat session and complete recall runtime ports before execution.
  • Required non-empty summaries before runtime handoff can append an anchor.
  • Made per-conversation tool mappings authoritative while preserving the draft-to-first-session compatibility path.
  • Added an idempotent startup migration that removes legacy Tape entries from:
    • Session disabled-tool lists
    • DeepChat Agent configuration
  • Preserved session timestamps, conversation ordering, environment recency, messages, Tape entries, and replay manifests during migration.
  • Added explicit exposure assertions at Agent tool assembly sites.

Summary by CodeRabbit

  • New Features

    • Added separate tool catalogs for runtime use and user-configurable settings.
    • Limited model-facing Tape tools to paired search and context capabilities.
    • Added stronger conversation-specific tool exposure and mapping controls.
    • Added validation requiring a non-empty summary for Tape handoffs.
  • Bug Fixes

    • Improved cleanup and normalization of disabled agent tools during startup.
    • Prevented unavailable or non-configurable tools from being executed or incorrectly restored.
  • Documentation

    • Added and updated architecture specifications covering Tape capability layering, tool exposure, and session cleanup.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR restricts Agent Tape tools to the atomic tape_search/tape_context recall pair for model use, introduces an exposure-policy layer to separate runtime and user-configurable tool catalogs, validates Tape handoff state, tightens disabledAgentTools normalization, and renames the disabled-tool cleanup migration/hook to v2, updating documentation and tests accordingly.

Changes

Tape Capability Layering

Layer / File(s) Summary
Exposure policy contracts
src/shared/agentTools.ts, src/shared/types/agent-interface.d.ts, src/shared/types/presenters/tool.presenter.d.ts
Adds TAPE_TOOL_NAMES, AgentToolExposure, exposure lookup/assert helpers, AgentTapeHandoffState, and the getConfigurableAgentToolDefinitions interface method.
Tape model boundary
src/main/presenter/toolPresenter/agentTools/agentTapeTools.ts, ...agentToolManager.ts, ...runtimePorts.ts, src/main/presenter/index.ts, ...agentTools/index.ts, ...toolPresenter/index.ts (prompt), tests
Narrows AgentTapeToolHandler and tool-call routing/definitions/prompt to only tape_search/tape_context, removes diagnostic/handoff methods from runtime ports and presenter tool runtime.
Runtime vs configurable catalog split
src/main/presenter/toolPresenter/index.ts, src/main/routes/index.ts, src/renderer/api/ToolClient.ts, DeepChatAgentsSettings.vue, McpIndicator.vue, tests
Adds getConfigurableAgentToolDefinitions for user-configurable-only tools without runtime side effects, wires it through the route/client/UI, and adjusts mapping fallback behavior.
Tape handoff state validation
agentSharedData.ts, agentRuntimePresenter/index.ts, tapeService.ts, projectionCoordinator.ts, tests
Requires a typed non-empty summary for Tape handoff via normalizeTapeHandoffState, updating handoffTape/handoff/handoffResult signatures.
disabledAgentTools normalization
agentSessionNormalization.ts, deepChatAgentRepository.ts, deferredToolExecutor.ts, tests
Filters disabled tools by user-configurable status, applies explicit-field normalization on config merge/persist, and refines error messaging.
Disabled-tool cleanup migration/hook rename
sessionDataMigrations.ts, disabledAgentToolCleanupHook.ts, hooks/index.ts, sqliteMainlineNormalizationHook.ts, architecture-guard.mjs, tests
Replaces v1 search-tool cleanup with runDisabledAgentToolCapabilityCleanupMigration (v2) and disabledAgentToolCleanupHook, with SQLite-backed batching/rollback tests.
Architecture documentation
docs/architecture/*
Updates memory-system, tape-baseline, session-boundary-cleanup, and tool-system docs, and adds new tape-capability-layering plan/spec/tasks docs.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Model
  participant AgentToolManager
  participant AgentTapeToolHandler
  participant RuntimePort

  Model->>AgentToolManager: callTool(tape_search / tape_context)
  AgentToolManager->>AgentTapeToolHandler: isModelTool(toolName)
  AgentTapeToolHandler-->>AgentToolManager: true
  AgentToolManager->>AgentTapeToolHandler: call(toolName, args)
  AgentTapeToolHandler->>RuntimePort: searchTape / getTapeContext
  RuntimePort-->>AgentTapeToolHandler: result
  AgentTapeToolHandler-->>Model: tape result

  Model->>AgentToolManager: callTool(tape_handoff)
  AgentToolManager->>AgentTapeToolHandler: isModelTool(tape_handoff)
  AgentTapeToolHandler-->>AgentToolManager: false
  AgentToolManager-->>Model: error - not available to model
Loading
sequenceDiagram
  participant Renderer
  participant ToolClient
  participant Route
  participant ToolPresenter

  Renderer->>ToolClient: getConfigurableAgentToolDefinitions(context)
  ToolClient->>Route: tools.listDefinitions(context)
  Route->>ToolPresenter: getConfigurableAgentToolDefinitions(context)
  ToolPresenter->>ToolPresenter: filter user-configurable tools
  ToolPresenter-->>Route: MCPToolDefinition[]
  Route-->>ToolClient: tools
  ToolClient-->>Renderer: tools
Loading

Possibly related PRs

  • ThinkInAIXYZ/deepchat#1669: Introduced the full session tape memory and tape tool/runtime APIs (getTapeInfo, listTapeAnchors, handoffTape) that this PR removes from the model boundary and runtime port.
  • ThinkInAIXYZ/deepchat#1959: Modifies the same DeepChatTapeService handoff flow (handoff/handoffResult) that this PR extends with AgentTapeHandoffState validation.
  • ThinkInAIXYZ/deepchat#1957: Introduced the disabled-search-tool cleanup migration/hook that this PR upgrades to the v2 disabled-agent-tool-capability cleanup.

Suggested reviewers: zerob13, zhangmo8

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR also adds handoff validation, startup cleanup migration, and config-normalization work that is not required by the visibility bug. Split the handoff, migration, and normalization changes into separate PRs unless they are needed to fix the linked visibility issue.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main Tape capability separation change.
Linked Issues check ✅ Passed The changes address the reported agent-tape visibility gap by separating runtime and configurable tool exposure so Tape tools can be available at conversation start.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tape-capability-layering

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/renderer/settings/components/DeepChatAgentsSettings.vue (1)

1473-1478: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove redundant tool source filter.

Since getConfigurableAgentToolDefinitions is explicitly scoped by the backend to return only user-configurable agent tools (as verified in the updated tests), filtering by tool.source === 'agent' on the client side is redundant and can be safely removed.

♻️ Proposed refactor
-    const definitions = await toolClient.getConfigurableAgentToolDefinitions({ chatMode: 'agent' })
-    tools.value = Array.isArray(definitions)
-      ? definitions
-          .filter((tool) => tool.source === 'agent')
-          .sort((a, b) => a.function.name.localeCompare(b.function.name))
-      : []
+    const definitions = await toolClient.getConfigurableAgentToolDefinitions({ chatMode: 'agent' })
+    tools.value = Array.isArray(definitions)
+      ? definitions.sort((a, b) => a.function.name.localeCompare(b.function.name))
+      : []
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/settings/components/DeepChatAgentsSettings.vue` around lines
1473 - 1478, Remove the redundant `tool.source === 'agent'` filter from the
`getConfigurableAgentToolDefinitions` result handling in the settings component.
Preserve the existing alphabetical sort by `a.function.name` and the empty-array
fallback for non-array responses.
src/shared/agentTools.ts (1)

28-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove redundant type assertion.

Since isTapeToolName(toolName) acts as a type guard that narrows toolName to TapeToolName, the explicit as TapeToolName cast is redundant and can be safely removed.

♻️ Proposed refactor
-export const getAgentToolExposure = (toolName: string): AgentToolExposure =>
-  isTapeToolName(toolName)
-    ? AGENT_TOOL_EXPOSURE_BY_NAME[toolName as TapeToolName]
-    : 'user-configurable'
+export const getAgentToolExposure = (toolName: string): AgentToolExposure =>
+  isTapeToolName(toolName)
+    ? AGENT_TOOL_EXPOSURE_BY_NAME[toolName]
+    : 'user-configurable'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/agentTools.ts` around lines 28 - 32, Remove the redundant type
assertion `as TapeToolName` from the AGENT_TOOL_EXPOSURE_BY_NAME array access
within the getAgentToolExposure function. The isTapeToolName type guard already
narrows the toolName parameter to TapeToolName in the true branch of the
ternary, so TypeScript can infer the correct type without the explicit cast.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/main/presenter/startupMigrations/sessionDataMigrations.sqlite.test.ts`:
- Around line 8-19: Keep the existing fallback that catches failure to import
better-sqlite3-multiple-ciphers, but remove catch handlers from the conditional
imports of newSessions, newSessionDisabledAgentTools, and newEnvironments,
including the corresponding imports around the later migration setup. Ensure
table-module import failures propagate and fail the test suite instead of
disabling it.

---

Nitpick comments:
In `@src/renderer/settings/components/DeepChatAgentsSettings.vue`:
- Around line 1473-1478: Remove the redundant `tool.source === 'agent'` filter
from the `getConfigurableAgentToolDefinitions` result handling in the settings
component. Preserve the existing alphabetical sort by `a.function.name` and the
empty-array fallback for non-array responses.

In `@src/shared/agentTools.ts`:
- Around line 28-32: Remove the redundant type assertion `as TapeToolName` from
the AGENT_TOOL_EXPOSURE_BY_NAME array access within the getAgentToolExposure
function. The isTapeToolName type guard already narrows the toolName parameter
to TapeToolName in the true branch of the ternary, so TypeScript can infer the
correct type without the explicit cast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ad60e7d-c613-444b-85ca-4ccbfc676c78

📥 Commits

Reviewing files that changed from the base of the PR and between 8c1e5a4 and 1a8b4fa.

📒 Files selected for processing (47)
  • docs/architecture/agent-memory-system/spec.md
  • docs/architecture/deepchat-tape-baseline/spec.md
  • docs/architecture/session-boundary-cleanup/spec.md
  • docs/architecture/tape-capability-layering/plan.md
  • docs/architecture/tape-capability-layering/spec.md
  • docs/architecture/tape-capability-layering/tasks.md
  • docs/architecture/tool-system.md
  • scripts/architecture-guard.mjs
  • src/main/agent/deepchat/deepChatAgentRepository.ts
  • src/main/agent/shared/agentSessionNormalization.ts
  • src/main/agent/shared/agentSharedData.ts
  • src/main/presenter/agentRuntimePresenter/deferredToolExecutor.ts
  • src/main/presenter/agentRuntimePresenter/index.ts
  • src/main/presenter/agentRuntimePresenter/tapeService.ts
  • src/main/presenter/index.ts
  • src/main/presenter/lifecyclePresenter/hooks/after-start/disabledAgentToolCleanupHook.ts
  • src/main/presenter/lifecyclePresenter/hooks/after-start/sqliteMainlineNormalizationHook.ts
  • src/main/presenter/lifecyclePresenter/hooks/index.ts
  • src/main/presenter/sessionApplication/projectionCoordinator.ts
  • src/main/presenter/startupMigrations/sessionDataMigrations.ts
  • src/main/presenter/toolPresenter/agentTools/agentTapeTools.ts
  • src/main/presenter/toolPresenter/agentTools/agentToolManager.ts
  • src/main/presenter/toolPresenter/agentTools/index.ts
  • src/main/presenter/toolPresenter/index.ts
  • src/main/presenter/toolPresenter/runtimePorts.ts
  • src/main/routes/index.ts
  • src/renderer/api/ToolClient.ts
  • src/renderer/settings/components/DeepChatAgentsSettings.vue
  • src/renderer/src/components/chat-input/McpIndicator.vue
  • src/shared/agentTools.ts
  • src/shared/types/agent-interface.d.ts
  • src/shared/types/presenters/tool.presenter.d.ts
  • test/main/agent/deepchat/deepChatAgentRepository.test.ts
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • test/main/presenter/agentRuntimePresenter/tapeService.test.ts
  • test/main/presenter/lifecyclePresenter/startupMaintenanceHooks.test.ts
  • test/main/presenter/sessionApplication/agentAssignmentPolicy.test.ts
  • test/main/presenter/sessionApplication/projectionCoordinator.test.ts
  • test/main/presenter/startupMigrations/sessionDataMigrations.sqlite.test.ts
  • test/main/presenter/startupMigrations/sessionDataMigrations.test.ts
  • test/main/presenter/toolPresenter/agentTools/agentTapeTools.test.ts
  • test/main/presenter/toolPresenter/toolPresenter.test.ts
  • test/main/routes/dispatcher.test.ts
  • test/main/scripts/architectureGuard.test.ts
  • test/renderer/api/clients.test.ts
  • test/renderer/components/DeepChatAgentsSettings.test.ts
  • test/renderer/components/McpIndicator.test.ts
💤 Files with no reviewable changes (2)
  • src/main/presenter/index.ts
  • src/main/presenter/toolPresenter/runtimePorts.ts

Comment on lines +8 to +19
const sqliteModule = await import('better-sqlite3-multiple-ciphers').catch(() => null)
const sessionsModule = sqliteModule
? await import('@/presenter/sqlitePresenter/tables/newSessions').catch(() => null)
: null
const disabledToolsModule = sqliteModule
? await import('@/presenter/sqlitePresenter/tables/newSessionDisabledAgentTools').catch(
() => null
)
: null
const environmentsModule = sqliteModule
? await import('@/presenter/sqlitePresenter/tables/newEnvironments').catch(() => null)
: null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='test/main/presenter/startupMigrations/sessionDataMigrations.sqlite.test.ts'

echo '== file outline =='
ast-grep outline "$file" --view expanded || true

echo
echo '== relevant lines =='
sed -n '1,140p' "$file" | cat -n

Repository: ThinkInAIXYZ/deepchat

Length of output: 6987


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='test/main/presenter/startupMigrations/sessionDataMigrations.sqlite.test.ts'

wc -l "$file"
printf '\n--- lines 1-120 ---\n'
sed -n '1,120p' "$file" | cat -n
printf '\n--- import references ---\n'
rg -n "better-sqlite3-multiple-ciphers|newSessions|newSessionDisabledAgentTools|newEnvironments|skip|describe|it|test" "$file"

Repository: ThinkInAIXYZ/deepchat

Length of output: 7196


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  'src/presenter/sqlitePresenter/tables/newSessions.ts' \
  'src/presenter/sqlitePresenter/tables/newSessionDisabledAgentTools.ts' \
  'src/presenter/sqlitePresenter/tables/newEnvironments.ts' \
  'test/main/presenter/startupMigrations/sessionDataMigrations.sqlite.test.ts'
do
  if [ -f "$f" ]; then
    echo "== $f =="
    ast-grep outline "$f" --view expanded || true
    echo
    sed -n '1,220p' "$f" | cat -n | sed -n '1,220p'
    echo
  fi
done

Repository: ThinkInAIXYZ/deepchat

Length of output: 8304


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the actual table module paths if they differ from the guessed src/ prefix.
fd 'newSessions\.ts|newSessionDisabledAgentTools\.ts|newEnvironments\.ts' .

Repository: ThinkInAIXYZ/deepchat

Length of output: 357


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  'src/main/presenter/sqlitePresenter/tables/newSessions.ts' \
  'src/main/presenter/sqlitePresenter/tables/newSessionDisabledAgentTools.ts' \
  'src/main/presenter/sqlitePresenter/tables/newEnvironments.ts'
do
  echo "== $f =="
  ast-grep outline "$f" --view expanded || true
  echo
  sed -n '1,220p' "$f" | cat -n | sed -n '1,220p'
  echo
done

Repository: ThinkInAIXYZ/deepchat

Length of output: 20675


Do not catch the table-module imports. Lines 8-19 and 41-44: keep the better-sqlite3-multiple-ciphers fallback, but let the @/presenter/... imports fail so regressions in newSessions, newSessionDisabledAgentTools, or newEnvironments fail CI instead of skipping the suite.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/main/presenter/startupMigrations/sessionDataMigrations.sqlite.test.ts`
around lines 8 - 19, Keep the existing fallback that catches failure to import
better-sqlite3-multiple-ciphers, but remove catch handlers from the conditional
imports of newSessions, newSessionDisabledAgentTools, and newEnvironments,
including the corresponding imports around the later migration setup. Ensure
table-module import failures propagate and fail the test suite instead of
disabling it.

@zerob13 zerob13 merged commit ce480c2 into dev Jul 15, 2026
4 checks passed
@zhangmo8 zhangmo8 deleted the fix/tape-capability-layering branch July 16, 2026 01:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] agent-tape 在开启对话的时候不出来,第一次问的时候开始调用工具这时候显示出来了,这对吗

2 participants